package com.aiwiown.snackmq.common.serialization;

import com.aiwiown.snackmq.common.exception.SerializationException;
import com.aiwiown.snackmq.common.serialization.constants.SerializerAlgorithm;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonSyntaxException;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;

/**
 * A JSON-based serializer implementation using Google's Gson library.
 * It is now configured to handle complex map keys correctly and provides pretty printing.
 */
@Slf4j
public class JsonSerializer implements Serializer {

    // Standard, compact JSON for production use
    private static final Gson GSON = new GsonBuilder()
            .enableComplexMapKeySerialization()
            .create();

    // A separate Gson instance for pretty printing
    private static final Gson GSON_PRETTY = new GsonBuilder()
            .enableComplexMapKeySerialization()
            .setPrettyPrinting()
            .create();

    @Override
    public byte getAlgorithmId() {
        return SerializerAlgorithm.JSON;
    }

    @Override
    public byte[] serialize(Object obj) {
        if (obj == null) {
            return new byte[0];
        }
        try {
            String json = GSON.toJson(obj);
            return json.getBytes(StandardCharsets.UTF_8);
        } catch (Exception e) {
            log.error("Failed to serialize object to JSON: {}", obj, e);
            throw new SerializationException("Failed to serialize object to JSON", e);
        }
    }

    /**
     * --- 核心修复 ---
     * 简化并加固了异常处理逻辑。
     * 任何 JsonSyntaxException 都被视为反序列化失败，并被包装后抛出。
     */
    @Override
    public <T> T deserialize(byte[] data, Class<T> clazz) {
        if (data == null || data.length == 0) {
            return null;
        }
        String json = new String(data, StandardCharsets.UTF_8);
        try {
            return GSON.fromJson(json, clazz);
        } catch (JsonSyntaxException e) {
            log.error("Failed to deserialize JSON, syntax error. Class: {}, JSON: '{}'", clazz.getName(), json, e);
            throw new SerializationException("Failed to deserialize JSON due to invalid syntax or structure.", e);
        } catch (Exception e) {
            log.error("Failed to deserialize JSON to object of class {}: {}", clazz.getName(), json, e);
            throw new SerializationException("Failed to deserialize JSON due to an unexpected error.", e);
        }
    }

    /**
     * --- 核心修复 ---
     * 对处理泛型的方法也应用了同样健壮的异常处理。
     */
    @Override
    public <T> T deserialize(byte[] data, Type typeOfT) {
        if (data == null || data.length == 0) {
            return null;
        }
        String json = new String(data, StandardCharsets.UTF_8);
        try {
            return GSON.fromJson(json, typeOfT);
        } catch (JsonSyntaxException e) {
            log.error("Failed to deserialize JSON, syntax error. Type: {}, JSON: '{}'", typeOfT.getTypeName(), json, e);
            throw new SerializationException("Failed to deserialize JSON due to invalid syntax or structure.", e);
        } catch (Exception e) {
            log.error("Failed to deserialize JSON to generic type {}: {}", typeOfT.getTypeName(), json, e);
            throw new SerializationException("Failed to deserialize JSON due to an unexpected error.", e);
        }
    }

    /**
     * Converts an object to a nicely formatted JSON string for logging or debugging.
     *
     * @param obj The object to serialize.
     * @return A pretty-printed JSON string.
     */
    public String toPrettyJson(Object obj) {
        if (obj == null) {
            return "null";
        }
        try {
            return GSON_PRETTY.toJson(obj);
        } catch (Exception e) {
            log.error("Failed to serialize object to pretty JSON: {}", obj, e);
            // Fallback to non-pretty JSON on error
            return GSON.toJson(obj);
        }
    }
}